package top.xxyu.shiro;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * shiro 配置类 相当于shiro 的配置文件
 * 
 * @author xx
 *
 */
@Configuration
public class ShiroConfiguration {

	@Bean
	public EhCacheManager getCacheManager() {
		EhCacheManager ehCacheManager = new EhCacheManager();
		ehCacheManager.setCacheManagerConfigFile("classpath:ehcache/ehcache.xml");

		return ehCacheManager;
	}

	@Bean
	public PermissionFilter permissionFilter() {
		return new PermissionFilter();

	}

	@Bean
	public DefaultWebSessionManager defaultWebSessionManager() {
		DefaultWebSessionManager session = new DefaultWebSessionManager();
		session.setGlobalSessionTimeout(1000 * 60 * 30);
		return session;
	}

	/**
	 * 自定义密码比较器
	 * 
	 * @return
	 */
	@Bean(name = "credentialsMatcher")
	public CredentialsMatcher credentialsMatcher() {
		return new CredentialsMatcher();
	}

	/**
	 * 配置自定义的权限登录器 登陆、认证
	 * 
	 * @return
	 */
	@Bean(name = "authRealm")
	public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher mathcher) {
		AuthRealm authRealm = new AuthRealm();
		authRealm.setCredentialsMatcher(mathcher);
		authRealm.setCacheManager(getCacheManager());
		// userRealm.cachingEnabled：启用缓存，默认true；
		// userRealm.authenticationCachingEnabled：启用身份验证缓存，即缓存AuthenticationInfo信息，默认false；
		// userRealm.authenticationCacheName：缓存AuthenticationInfo信息的缓存名称；
		// userRealm.
		// authorizationCachingEnabled：启用授权缓存，即缓存AuthorizationInfo信息，默认false；
		// userRealm. authorizationCacheName：缓存AuthorizationInfo信息的缓存名称；

		return authRealm;
	}

	/**
	 * 配置安全事务管理器
	 * 
	 * @param authRealm
	 * @return
	 */
	@Bean("securityManager")
	public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
		System.out.println("------------shiro 已经加载-----------");
		DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//		 <!-- 配置你需要使用的Realms -->
		manager.setRealm(authRealm);
		// <!-- 定义要使用的session管理器 -->
		manager.setSessionManager(defaultWebSessionManager());
		return manager;
	}

	/**
	 * Shiro生命周期处理器
	 * 
	 * @return
	 */
	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	/**
	 * shiro 权限控制 @Qualifier("指定实现类，可能一个接口多实现")
	 * 
	 * @param securityManager
	 * @return
	 */
	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
		ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
		filterFactoryBean.setSecurityManager(securityManager);
		// 配置登录的url和登录成功的url
		filterFactoryBean.setLoginUrl("/login");
		filterFactoryBean.setSuccessUrl("/index");
		filterFactoryBean.setUnauthorizedUrl("/index");
		Map<String, Filter> map = new HashMap<>();
		map.put("psf", permissionFilter());
		filterFactoryBean.setFilters(map);
		// 配置访问权限
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		// anon 表示可以匿名访问
		filterChainDefinitionMap.put("/admin/login.ftl", "anon");
		filterChainDefinitionMap.put("/mobile/**", "anon");
		filterChainDefinitionMap.put("/upload/**", "anon");
		filterChainDefinitionMap.put("/loginUser", "anon");
		// authc表示需要认证才可以访问
		// filterChainDefinitionMap.put("/*", "authc");
		filterChainDefinitionMap.put("/**", "authc");
		// filterChainDefinitionMap.put("/*.*", "authc");

		// filterChainDefinitionMap.put("/loginUser", "anon");
		// filterChainDefinitionMap.put("/logout*", "anon");
		// filterChainDefinitionMap.put("/jsp/error.jsp*", "anon");
		// filterChainDefinitionMap.put("/jsp/index.jsp*", "authc");
		filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return filterFactoryBean;
	}

	/**
	 * 代理哪个类，不清楚 应该是 setAdvice(具体类)
	 * 
	 * @param manager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
			@Qualifier("securityManager") SecurityManager manager) {
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(manager);
		return advisor;
	}

	/**
	 * spring 自动动态代理 aop
	 * 
	 * @return
	 */
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		// 没有接口，直接代理
		defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
		return defaultAdvisorAutoProxyCreator;
	}
}
